namespace Zaggit.DomainObjects
{
    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.ComponentModel;

    /// <summary>
    /// Provides a list of online users.
    /// </summary>
    public class OnlineUsers : IBindingList, ITypedList
    {
        #region Fields

        private readonly PropertyDescriptorCollection _Properties;

        private readonly List<User> _Store;

        #endregion

        #region Events

        public event ListChangedEventHandler ListChanged;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the OnlineUsers class.
        /// </summary>
        public OnlineUsers()
        {
            _Store = new List<User>();
            PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(typeof(User), new Attribute[] { new BrowsableAttribute(true) });
            _Properties = pdc.Sort();

        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets whether you can update items in the list.
        /// </summary>
        /// <returns>true if you can update the items in the list; otherwise, false.</returns>
        public bool AllowEdit
        {
            get { return true; }
        }

        /// <summary>
        /// Gets whether you can add items to the list using <see cref="M:System.ComponentModel.IBindingList.AddNew" />.
        /// </summary>
        /// <returns>true if you can add items to the list using <see cref="M:System.ComponentModel.IBindingList.AddNew" />; otherwise, false.</returns>
        public bool AllowNew
        {
            get { return true; }
        }

        /// <summary>
        /// Gets whether you can remove items from the list, using <see cref="M:System.Collections.IList.Remove(System.Object)" /> or <see cref="M:System.Collections.IList.RemoveAt(System.Int32)" />.
        /// </summary>
        /// <returns>true if you can remove items from the list; otherwise, false.</returns>
        public bool AllowRemove
        {
            get { return true; }
        }

        public int Count
        {
            get { return _Store.Count; }
        }

        public bool IsFixedSize
        {
            get { return false; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool IsSorted
        {
            get { return true; }
        }

        public bool IsSynchronized
        {
            get { return false; }
        }

        public object this[int index]
        {
            get
            {
                if (index < 0) return null;
                return _Store[index];
            }
            set
            {
                _Store[index] = (User)value;
                ListChanged(this, new ListChangedEventArgs(ListChangedType.ItemChanged, index));
            }
        }

        public ListSortDirection SortDirection
        {
            get { return ListSortDirection.Ascending; }
        }

        public PropertyDescriptor SortProperty
        {
            get { return _Properties[0]; }
        }

        public bool SupportsChangeNotification
        {
            get { return false; }
        }

        public bool SupportsSearching
        {
            get { return true; }
        }

        public bool SupportsSorting
        {
            get { return true; }
        }

        public object SyncRoot
        {
            get { return _Store; }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Adds an item to the <see cref="T:System.Collections.IList" />.
        /// </summary>
        /// <param name="value">The object to add to the <see cref="T:System.Collections.IList" />.</param>
        /// <returns>
        /// The position into which the new element was inserted, or -1 to indicate that the item was not inserted into the collection,
        /// </returns>
        public int Add(object value)
        {
            this._Store.Add((User)value);
            var index = this._Store.IndexOf((User)value);
            ListChanged(this, new ListChangedEventArgs(ListChangedType.ItemAdded, index));
            return index;
        }

        public void AddIndex(PropertyDescriptor property)
        {
            throw new NotImplementedException();
        }

        public object AddNew()
        {
            throw new NotImplementedException();
        }

        public void ApplySort(PropertyDescriptor property, ListSortDirection direction)
        {
            _Store.Reverse();
            return;
        }

        public void Clear()
        {
            this._Store.Clear();
            ListChanged(null, null);
        }

        public bool Contains(object value)
        {
            return _Store.Contains((User)value);
        }

        public void CopyTo(Array array, int index)
        {
            throw new NotImplementedException();
        }

        public int Find(PropertyDescriptor property, object key)
        {
            var user = this._Store.FirstOrDefault(u => u.UserName == (string)key);
            return IndexOf(user);
        }

        public System.Collections.IEnumerator GetEnumerator()
        {
            return this._Store.GetEnumerator();
        }

        public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
        {
            return _Properties;
        }

        public string GetListName(PropertyDescriptor[] listAccessors)
        {
            return typeof(User).Name;
        }

        public int IndexOf(object value)
        {
            return this._Store.IndexOf((User)value);
        }

        public void Insert(int index, object value)
        {
            this._Store.Insert(index, (User)value);
            ListChanged(this, new ListChangedEventArgs(ListChangedType.ItemAdded, index));
        }

        public void Remove(object value)
        {
            var index = this._Store.IndexOf((User)value);
            this._Store.Remove((User)value);
            ListChanged(this, new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
        }

        public void RemoveAt(int index)
        {
            this._Store.RemoveAt(index);
            ListChanged(this, new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
        }

        public void RemoveIndex(PropertyDescriptor property)
        {
            throw new NotImplementedException();
        }

        public void RemoveSort()
        {
            throw new NotImplementedException();
        }

        #endregion

    }
}